﻿namespace Sai.Core.Sandcastle
{
	using System.Collections.Generic;
	using System.Collections.ObjectModel;
	using System.Xml;

	public class Topic
	{
		private Dictionary<string, string> attributes = new Dictionary<string, string>();

		private const string IdAttributeText = "id";
		private const string TitleAttributeText = "title";

		public Topic()
		{
			this.Children = new TopicCollection();
		}
		
		public Topic(string id, string title)
			: this()
		{
			this.Id = id;
			this.Title = title;
		}

		private string Id 
		{ 
			get
			{
				if (this.attributes.ContainsKey(IdAttributeText))
				{
					return this.attributes[IdAttributeText];
				}

				return string.Empty;
			}

			set
			{
				if (this.attributes.ContainsKey(IdAttributeText))
				{
					this.attributes[IdAttributeText] = value;
				}
				else
				{
					this.attributes.Add(IdAttributeText, value);
				}
			}
		}

		private string Title 
		{
			get
			{
				if (this.attributes.ContainsKey(TitleAttributeText))
				{
					return this.attributes[TitleAttributeText];
				}

				return string.Empty;
			}

			set
			{
				if (this.attributes.ContainsKey(TitleAttributeText))
				{
					this.attributes[TitleAttributeText] = value;
				}
				else
				{
					this.attributes.Add(TitleAttributeText, value);
				}
			}
		}
				
		public string Path { get; set; }

		private TopicCollection Children
		{
			get;
			set;
		}

		public void Add(Topic topic)
		{
			this.Children.Add(topic);
		}

		public void Add(IEnumerable<Topic> topics)
		{
			foreach (var topic in topics)
			{
				this.Children.Add(topic);
			}
		}

		public void ClearChildren()
		{
			this.Children.Clear();
		}

		public void ReplaceChildren(Topic fromTopic)
		{
			this.ClearChildren();

			this.Title = fromTopic.Title;

			foreach (var topic in fromTopic.Children)
			{
				this.Children.Add(topic);
			}
		}

		public Topic SearchByGuid(string guid)
		{
			return this.Children.SearchByGuid(guid);
		}

		public ReadOnlyCollection<Topic> Content
		{
			get
			{
				return new ReadOnlyCollection<Topic>(this.Children);
			}
		}

		public ReadOnlyCollection<string> FlatTopicIds
		{
			get
			{
				List<string> ids = new List<string>();

				ids.Add(this.Id);

				foreach (var topic in this.Children)
				{
					ids.AddRange(topic.FlatTopicIds);
				}

				return new ReadOnlyCollection<string>(ids);
			}
		}

		public void WriteXml(XmlWriter writer)
		{
			writer.WriteStartElement("Topic");

			foreach (string key in this.attributes.Keys)
			{
				string value = this.attributes[key];

				writer.WriteAttributeString(key, value);
			}

			foreach (Topic topic in this.Children)
			{
				topic.WriteXml(writer);
			}

			writer.WriteEndElement();
		}

		public void LoadNode(XmlNode node)
		{
			if (node != null)
			{
				foreach (XmlAttribute attribute in node.Attributes)
				{
					this.attributes.Add(attribute.Name, attribute.Value);
				}

				if (node.ChildNodes.Count != 0)
				{
					foreach (XmlNode childSite in node.ChildNodes)
					{
						var child = new Topic();
						child.LoadNode(childSite);
						
						this.Children.Add(child);
					}
				}
			}
		}
		
		public bool Matches(string id)
		{
			bool isMatch = false;

			if (!string.IsNullOrEmpty(this.Id) && !string.IsNullOrEmpty(id))
			{
				isMatch = string.Compare(this.Id, id, true) == 0;
			}

			return isMatch;
		}
	}
}
